// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod steam_setup;
mod config;
mod frp_setup;
mod scum_control;
mod status_monitor;

use steam_setup::SteamSetup;
use frp_setup::FrpSetup;
use config::AppConfig;
use scum_control::ScumControl;
use status_monitor::StatusMonitor;
use std::collections::HashMap;
use std::sync::Mutex;
use tauri::State;
use tauri::Manager;
use std::sync::Arc;
use std::time::Duration;
use std::thread;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use serde::{Serialize, Deserialize};
use windows_sys::Win32::System::Console::{AllocConsole, GetConsoleWindow};
use windows_sys::Win32::UI::WindowsAndMessaging::{ShowWindow, SW_HIDE};

#[tauri::command]
async fn download_steamcmd(install_path: String, window: tauri::Window) -> Result<String, String> {
    // 保存安装路径到配置（初始状态为未安装）
    let mut config = AppConfig::load()?;
    config.update_install_path(install_path.clone(), false)?;
    
    SteamSetup::download_and_install_steamcmd(install_path, window).await
}

#[tauri::command]
fn get_config() -> Result<AppConfig, String> {
    AppConfig::load()
}

#[tauri::command]
fn save_install_path(install_path: String, installed: bool) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.update_install_path(install_path, installed)
}

#[tauri::command]
fn get_setting(key: String) -> Result<Option<String>, String> {
    let config = AppConfig::load()?;
    Ok(config.get_setting(&key).cloned())
}

#[tauri::command]
fn set_setting(key: String, value: String) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.set_setting(key, value)
}

#[tauri::command]
fn get_server_exe_path() -> Result<String, String> {
    let config = AppConfig::load()?;
    Ok(config.get_scum_server_exe_path().to_string())
}

#[tauri::command]
fn mark_installation_complete(install_path: String) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.update_install_path(install_path, true)
}

#[tauri::command]
fn get_frp_config() -> Result<(String, bool, bool), String> {
    let config = AppConfig::load()?;
    Ok((config.frp_dir.clone(), config.frp_installed, config.frp_running))
}

#[tauri::command]
fn save_frp_path(frp_dir: String, installed: bool) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.update_frp_path(frp_dir, installed)
}

#[tauri::command]
fn set_frp_running(running: bool) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.set_frp_running(running)
}

#[tauri::command]
fn check_frp_installed() -> Result<bool, String> {
    let config = AppConfig::load()?;
    Ok(config.is_frp_installed())
}

#[tauri::command]
async fn download_frp(frp_dir: String, window: tauri::Window) -> Result<String, String> {
    // 保存 FRP 路径到配置（初始状态为未安装）
    let mut config = AppConfig::load()?;
    config.update_frp_path(frp_dir.clone(), false)?;
    
    FrpSetup::download_and_install_frp(frp_dir, window).await
}

#[tauri::command]
fn start_frp() -> Result<(), String> {
    let config = AppConfig::load()?;
    if config.frp_dir.is_empty() {
        return Err("FRP 路径未配置".to_string());
    }
    
    // 在启动前生成配置文件
    FrpSetup::generate_frp_config_from_settings(config.frp_dir.clone())?;
    
    // 启动FRP服务
    FrpSetup::start_frp(config.frp_dir.clone())?;
    
    // 启动FRP日志监控
    unsafe {
        let monitor_ptr = &raw mut FRP_LOG_MONITOR;
        if let Some(monitor) = &mut *monitor_ptr {
            monitor.start_monitoring(config.frp_dir);
        }
    }
    
    Ok(())
}

#[tauri::command]
fn stop_frp() -> Result<(), String> {
    // 停止FRP日志监控
    unsafe {
        let monitor_ptr = &raw const FRP_LOG_MONITOR;
        if let Some(monitor) = &*monitor_ptr {
            monitor.stop_monitoring();
        }
    }
    
    // 停止FRP服务
    FrpSetup::stop_frp()?;
    
    // 更新配置状态
    let mut config = AppConfig::load()?;
    config.set_frp_running(false)?;
    
    Ok(())
}

#[tauri::command]
fn save_frp_config(config_content: String) -> Result<(), String> {
    let config = AppConfig::load()?;
    if config.frp_dir.is_empty() {
        return Err("FRP 路径未配置".to_string());
    }
    FrpSetup::save_frp_config(config.frp_dir, config_content)
}

#[tauri::command]
fn get_frp_config_item(key: String) -> Result<Option<String>, String> {
    let config = AppConfig::load()?;
    Ok(config.get_frp_config(&key).cloned())
}

#[tauri::command]
fn set_frp_config_item(key: String, value: String) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.set_frp_config(key, value)
}

#[tauri::command]
fn get_frp_config_all() -> Result<HashMap<String, String>, String> {
    let config = AppConfig::load()?;
    Ok(config.get_frp_config_all().clone())
}

#[tauri::command]
fn set_frp_config_all(frp_config: HashMap<String, String>) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.set_frp_config_all(frp_config)
}

#[tauri::command]
fn generate_frp_config() -> Result<(), String> {
    let config = AppConfig::load()?;
    if config.frp_dir.is_empty() {
        return Err("FRP 路径未配置".to_string());
    }
    FrpSetup::generate_frp_config_from_settings(config.frp_dir)
}

#[tauri::command]
fn set_scum_server_running(running: bool) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.set_scum_server_running(running)
}

#[tauri::command]
fn get_service_status(scum_control: State<'_, Mutex<ScumControl>>) -> Result<(bool, bool), String> {
    let config = AppConfig::load()?;
    
    // 检查FRP是否真的在运行
    let frp_running = FrpSetup::is_frp_running();
    
    // 检查SCUM服务器是否真的在运行
    let control = scum_control.lock().unwrap();
    let scum_running = control.is_running();
    
    // 如果检测到的状态与配置中的状态不一致，更新配置
    if scum_running != config.scum_server_running {
        println!("SCUM状态不一致，更新配置并发送事件");
        // 在另一个线程中更新配置，避免死锁
        let window = control.get_window().cloned();
        thread::spawn(move || {
            if let Ok(mut config) = AppConfig::load() {
                let _ = config.set_scum_server_running(scum_running);
                
                // 发送状态变化事件到前端
                if let Some(window) = window {
                    let status = if scum_running { "running" } else { "stopped" };
                    println!("发送SCUM状态变化事件: {}", status);
                    let _ = window.emit("scum_status_changed", status);
                } else {
                    println!("警告: window为None，无法发送事件");
                }
            }
        });
    }
    
    // 如果FRP状态不一致，更新配置
    if frp_running != config.frp_running {
        println!("FRP状态不一致，更新配置并发送事件");
        let window = control.get_window().cloned();
        thread::spawn(move || {
            if let Ok(mut config) = AppConfig::load() {
                let _ = config.set_frp_running(frp_running);
                
                // 发送状态变化事件到前端
                if let Some(window) = window {
                    let status = if frp_running { "running" } else { "stopped" };
                    println!("发送FRP状态变化事件: {}", status);
                    let _ = window.emit("frp_status_changed", status);
                } else {
                    println!("警告: window为None，无法发送事件");
                }
            }
        });
    }
    
    Ok((frp_running, scum_running))
}

#[tauri::command]
fn add_auto_restart_task(task: crate::config::AutoRestartTask) -> Result<(), String> {
    println!("收到添加任务请求: {:?}", task); // 调试日志
    let mut config = AppConfig::load()?;
    config.add_auto_restart_task(task)
}

#[tauri::command]
fn remove_auto_restart_task(task_id: String) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.remove_auto_restart_task(&task_id)
}

#[tauri::command]
fn update_auto_restart_task(task_id: String, enabled: bool) -> Result<(), String> {
    let mut config = AppConfig::load()?;
    config.update_auto_restart_task(&task_id, enabled)
}

#[tauri::command]
fn get_auto_restart_tasks() -> Result<Vec<crate::config::AutoRestartTask>, String> {
    let config = AppConfig::load()?;
    Ok(config.get_auto_restart_tasks().clone())
}

#[tauri::command]
fn start_scum_server(scum_control: State<'_, Mutex<ScumControl>>, window: tauri::Window) -> Result<(), String> {
    let config = AppConfig::load()?;
    let exe_path = config.get_scum_server_exe_path();
    
    if exe_path.is_empty() {
        return Err("SCUM服务器路径未配置".to_string());
    }
    
    let mut control = scum_control.lock().unwrap();
    control.set_window(window);
    control.start_server(&exe_path)
}

#[tauri::command]
async fn restart_scum_server(scum_control: State<'_, Mutex<ScumControl>>, window: tauri::Window) -> Result<(), String> {
    let config = AppConfig::load()?;
    let exe_path = config.get_scum_server_exe_path();
    
    if exe_path.is_empty() {
        return Err("SCUM服务器路径未配置".to_string());
    }
    
    // 先停止服务器
    {
        let mut control = scum_control.lock().unwrap();
        control.set_window(window.clone());
        let _ = control.stop_server();
    }
    
    // 等待进程完全停止，最多等待5秒
    let mut waited = 0;
    let max_wait = 5;
    loop {
        let is_running = {
            let control = scum_control.lock().unwrap();
            control.is_running()
        };
        
        if !is_running {
            break;
        }
        
        tokio::time::sleep(Duration::from_secs(1)).await;
        waited += 1;
        
        if waited >= max_wait {
            println!("等待停止超时，强制继续启动");
            break;
        }
    }
    
    // 启动服务器
    {
        let mut control = scum_control.lock().unwrap();
        control.start_server(&exe_path)?;
    }
    
    // 启动状态监控线程，每500ms检查一次状态，直到10秒超时或状态变为运行
    let window_clone = window.clone();
    
    // 使用tokio::spawn而不是thread::spawn，这样可以避免生命周期问题
    tokio::spawn(async move {
        let mut checked_count = 0;
        let max_checks = 20; // 10秒 / 500ms = 20次
        
        loop {
            tokio::time::sleep(Duration::from_millis(500)).await;
            
            // 由于我们不能在异步任务中直接访问scum_control，我们通过事件来通知前端
            // 前端可以调用get_service_status来获取最新状态
            
            checked_count += 1;
            
            // 发送状态检查事件到前端
            let _ = window_clone.emit("restart_status_check", checked_count);
            
            // 如果达到最大检查次数，退出循环
            if checked_count >= max_checks {
                println!("重启状态监控结束: 检查次数={}", checked_count);
                break;
            }
        }
    });
    
    Ok(())
}

#[tauri::command]
async fn stop_scum_server(scum_control: State<'_, Mutex<ScumControl>>) -> Result<(), String> {
    // 先尝试停止服务器
    let needs_wait = {
        let mut control = scum_control.lock().unwrap();
        control.stop_server()?
    };
    
    // 如果需要等待优雅关闭
    if needs_wait {
        // 等待一段时间让服务器优雅关闭
        tokio::time::sleep(Duration::from_secs(360)).await;
        
        // 检查进程是否已经结束
        let is_still_running = {
            let control = scum_control.lock().unwrap();
            control.is_running()
        };
        
        if is_still_running {
            // 如果还在运行，强制终止
            let mut control = scum_control.lock().unwrap();
            control.stop_server()?;
        }
    }
    
    Ok(())
}

#[tauri::command]
fn get_scum_logs(scum_control: State<'_, Mutex<ScumControl>>) -> Result<Vec<String>, String> {
    let control = scum_control.lock().unwrap();
    
    // 检查SCUM服务器是否在运行
    if !control.is_running() {
        return Err("SCUM服务器未在运行，无法查看日志".to_string());
    }
    
    // 获取最近50行日志
    let logs = control.get_logs(50);
    Ok(logs)
}

#[tauri::command]
fn get_frp_logs() -> Result<Vec<String>, String> {
    let config = AppConfig::load()?;
    let frp_dir = config.frp_dir;
    
    if frp_dir.is_empty() {
        return Err("FRP路径未配置".to_string());
    }
    
    // 检查FRP是否在运行
    if !FrpSetup::is_frp_running() {
        return Err("FRP服务未在运行，无法查看日志".to_string());
    }
    
    // 尝试读取FRP日志文件
    let log_file = format!("{}\\frpc.log", frp_dir);
    if let Ok(content) = std::fs::read_to_string(&log_file) {
        // 分割成行并获取最后50行
        let lines: Vec<String> = content.lines().map(|s| s.to_string()).collect();
        let start = if lines.len() > 50 {
            lines.len() - 50
        } else {
            0
        };
        Ok(lines[start..].to_vec())
    } else {
        Ok(vec!["暂无FRP日志".to_string()])
    }
}

// 数据库管理相关命令
#[tauri::command]
fn get_database_files() -> Result<Vec<DatabaseFile>, String> {
    let config = AppConfig::load()?;
    if config.install_path.is_empty() {
        return Err("安装路径未配置".to_string());
    }
    
    let save_files_path = format!("{}\\steamapps\\common\\SCUM Server\\SCUM\\Saved\\SaveFiles", config.install_path);
    
    if !Path::new(&save_files_path).exists() {
        return Err("保存文件目录不存在".to_string());
    }
    
    let mut files = Vec::new();
    
    if let Ok(entries) = std::fs::read_dir(&save_files_path) {
        for entry in entries {
            if let Ok(entry) = entry {
                let path = entry.path();
                if let Some(file_name) = path.file_name() {
                    if let Some(name_str) = file_name.to_str() {
                        if name_str.ends_with(".db") || name_str.ends_with(".db-backup") || 
                           name_str.ends_with(".db-shm") || name_str.ends_with(".db-wal") {
                            
                            let file_type = if name_str == "SCUM.db" {
                                "当前数据库"
                            } else if name_str.ends_with(".db-backup") {
                                "自动备份"
                            } else if name_str.ends_with(".db-shm") {
                                "共享内存文件"
                            } else if name_str.ends_with(".db-wal") {
                                "预写日志文件"
                            } else {
                                "其他"
                            };
                            
                            let metadata = std::fs::metadata(&path);
                            let size = if let Ok(ref meta) = metadata {
                                format!("{:.2} MB", meta.len() as f64 / (1024.0 * 1024.0))
                            } else {
                                "未知".to_string()
                            };
                            
                            let modified = if let Ok(ref meta) = metadata {
                                if let Ok(time) = meta.modified() {
                                    if let Ok(duration) = time.duration_since(std::time::UNIX_EPOCH) {
                                        let datetime = chrono::DateTime::from_timestamp(duration.as_secs() as i64, 0);
                                        if let Some(dt) = datetime {
                                            dt.format("%Y-%m-%d %H:%M:%S").to_string()
                                        } else {
                                            "未知".to_string()
                                        }
                                    } else {
                                        "未知".to_string()
                                    }
                                } else {
                                    "未知".to_string()
                                }
                            } else {
                                "未知".to_string()
                            };
                            
                            files.push(DatabaseFile {
                                name: name_str.to_string(),
                                size,
                                modified_time: modified,
                                file_type: file_type.to_string(),
                                path: path.to_string_lossy().to_string(),
                            });
                        }
                    }
                }
            }
        }
    }
    
    // 按修改时间排序，最新的在前面
    files.sort_by(|a, b| b.modified_time.cmp(&a.modified_time));
    
    Ok(files)
}

#[tauri::command]
fn create_database_backup() -> Result<String, String> {
    let config = AppConfig::load()?;
    if config.install_path.is_empty() {
        return Err("安装路径未配置".to_string());
    }
    
    let current_db_path = format!("{}\\steamapps\\common\\SCUM Server\\SCUM\\Saved\\SaveFiles\\SCUM.db", config.install_path);
    if !Path::new(&current_db_path).exists() {
        return Err("当前数据库文件不存在".to_string());
    }
    
    let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
    let backup_name = format!("SCUM_Manual_Backup_{}.db-backup", timestamp);
    let backup_path = format!("{}\\steamapps\\common\\SCUM Server\\SCUM\\Saved\\SaveFiles\\{}", config.install_path, backup_name);
    
    // 复制数据库文件
    std::fs::copy(&current_db_path, &backup_path)
        .map_err(|e| format!("创建备份失败: {}", e))?;
    
    Ok(backup_name)
}

#[tauri::command]
fn restore_database_backup(scum_control: State<'_, Mutex<ScumControl>>, backup_path: String) -> Result<(), String> {
    // 检查SCUM服务器是否在运行
    let control = scum_control.lock().unwrap();
    if control.is_running() {
        return Err("请先关闭SCUM服务器后再进行数据库恢复操作！".to_string());
    }
    drop(control);

    let config = AppConfig::load()?;
    if config.install_path.is_empty() {
        return Err("安装路径未配置".to_string());
    }
    
    let current_db_path = format!("{}\\steamapps\\common\\SCUM Server\\SCUM\\Saved\\SaveFiles\\SCUM.db", config.install_path);
    
    // 检查备份文件是否存在
    if !Path::new(&backup_path).exists() {
        return Err("备份文件不存在".to_string());
    }
    
    // 先创建当前数据库的备份
    let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
    let safety_backup = format!("{}\\steamapps\\common\\SCUM Server\\SCUM\\Saved\\SaveFiles\\SCUM_Safety_Backup_{}.db-backup", config.install_path, timestamp);
    
    if Path::new(&current_db_path).exists() {
        std::fs::copy(&current_db_path, &safety_backup)
            .map_err(|e| format!("创建安全备份失败: {}", e))?;
    }
    
    // 恢复备份
    std::fs::copy(&backup_path, &current_db_path)
        .map_err(|e| format!("恢复备份失败: {}", e))?;
    
    Ok(())
}

#[tauri::command]
fn delete_database_backup(backup_path: String) -> Result<(), String> {
    if !Path::new(&backup_path).exists() {
        return Err("备份文件不存在".to_string());
    }
    
    std::fs::remove_file(&backup_path)
        .map_err(|e| format!("删除备份失败: {}", e))?;
    
    Ok(())
}

#[derive(Debug, Serialize, Deserialize)]
struct DatabaseFile {
    name: String,
    size: String,
    modified_time: String,
    file_type: String,
    path: String,
}

// 全局FRP日志监控器
struct FrpLogMonitor {
    window: Arc<Mutex<Option<tauri::Window>>>,
    running: Arc<Mutex<bool>>,
}

impl FrpLogMonitor {
    fn new() -> Self {
        Self {
            window: Arc::new(Mutex::new(None)),
            running: Arc::new(Mutex::new(false)),
        }
    }

    fn set_window(&mut self, window: tauri::Window) {
        let mut window_guard = self.window.lock().unwrap();
        *window_guard = Some(window);
    }

    fn start_monitoring(&mut self, frp_dir: String) {
        let window = Arc::clone(&self.window);
        let running = Arc::clone(&self.running);
        
        {
            let mut running_guard = running.lock().unwrap();
            if *running_guard {
                return; // 已经在运行
            }
            *running_guard = true;
        }

        thread::spawn(move || {
            let log_file = format!("{}\\frpc.log", frp_dir);
            
            // 如果日志文件不存在，创建一个空的
            if !Path::new(&log_file).exists() {
                let _ = File::create(&log_file);
            }
            
            // 获取当前文件大小，用于定位到文件末尾
            let mut last_size = std::fs::metadata(&log_file)
                .map(|m| m.len())
                .unwrap_or(0);
            
            loop {
                // 检查是否应该停止
                {
                    let running_guard = running.lock().unwrap();
                    if !*running_guard {
                        break;
                    }
                }

                thread::sleep(Duration::from_millis(100)); // 每100ms检查一次
                
                if let Ok(metadata) = std::fs::metadata(&log_file) {
                    let current_size = metadata.len();
                    
                    // 如果文件大小增加了，读取新内容
                    if current_size > last_size {
                        if let Ok(file) = File::open(&log_file) {
                            let mut reader = BufReader::new(file);
                            
                            // 跳过已读取的内容
                            let mut buffer = Vec::new();
                            reader.read_until(b'\n', &mut buffer).ok();
                            
                            // 读取新内容
                            for line in reader.lines() {
                                if let Ok(line_content) = line {
                                    // 发送日志到前端
                                    if let Some(window) = &*window.lock().unwrap() {
                                        let _ = window.emit("frp_log_update", line_content);
                                    }
                                }
                            }
                        }
                        last_size = current_size;
                    }
                }
            }
        });
    }

    fn stop_monitoring(&self) {
        let mut running_guard = self.running.lock().unwrap();
        *running_guard = false;
    }
}

// 全局FRP日志监控器实例
static mut FRP_LOG_MONITOR: Option<FrpLogMonitor> = None;

fn main() {
    tauri::Builder::default()
        .manage(Mutex::new(ScumControl::new()))
        .setup(|app| {
            // 初始化控制台
            unsafe {
                AllocConsole();
                // let hwnd = GetConsoleWindow();
                // if hwnd != std::ptr::null_mut() {
                //     // 隐藏控制台窗口
                //     ShowWindow(hwnd, SW_HIDE);
                // }
            }
            
            // 初始化FRP日志监控器
            unsafe {
                FRP_LOG_MONITOR = Some(FrpLogMonitor::new());
            }
            
            // 启动状态监听服务
            if let Some(window) = app.get_window("main") {
                // 设置FRP日志监控器的窗口
                unsafe {
                    let monitor_ptr = &raw mut FRP_LOG_MONITOR;
                    if let Some(monitor) = &mut *monitor_ptr {
                        monitor.set_window(window.clone());
                    }
                }
                
                // 获取管理的ScumControl实例并恢复状态
                let scum_control = app.state::<Mutex<ScumControl>>();
                let mut control = scum_control.lock().unwrap();
                control.set_window(window.clone());
                if let Err(e) = control.restore_process_state() {
                    println!("恢复SCUM服务器状态失败: {}", e);
                }
                
                // 创建一个新的ScumControl实例，复制已恢复的状态
                let mut new_control = ScumControl::new();
                new_control.set_window(window.clone());
                
                // 使用新实例创建状态监控器
                let scum_control_arc = Arc::new(Mutex::new(new_control));
                let mut status_monitor = StatusMonitor::new(scum_control_arc);
                status_monitor.set_window(window);
                status_monitor.start();
            }
            
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![
            download_steamcmd,
            get_config,
            save_install_path,
            get_setting,
            set_setting,
            get_server_exe_path,
            mark_installation_complete,
            get_frp_config,
            save_frp_path,
            set_frp_running,
            check_frp_installed,
            download_frp,
            start_frp,
            stop_frp,
            save_frp_config,
            get_frp_config_item,
            set_frp_config_item,
            get_frp_config_all,
            set_frp_config_all,
            generate_frp_config,
            set_scum_server_running,
            get_service_status,
            add_auto_restart_task,
            remove_auto_restart_task,
            update_auto_restart_task,
            get_auto_restart_tasks,
            start_scum_server,
            restart_scum_server,
            stop_scum_server,
            get_scum_logs,
            get_frp_logs,
            get_database_files,
            create_database_backup,
            restore_database_backup,
            delete_database_backup
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
